
package com.media.module.fragment;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.droid.utils.BitmapHelper;
import com.droid.utils.Fileutils;
import com.droid.utils.ProgressDialogHelper;
import com.droid.utils.ProgressDialogHelper.ProgressCallBack;
import com.media.module.R;
import com.media.module.interfaces.CameraParamsChangedListener;
import com.media.module.interfaces.FocusCallback;
import com.media.module.interfaces.KeyEventsListener;
import com.media.module.interfaces.PhotoTakenCallback;
import com.media.module.interfaces.RawPhotoTakenCallback;
import com.media.module.model.CameraMode;
import com.media.module.model.FacingMode;
import com.media.module.model.FlashMode;
import com.media.module.model.FocusMode;
import com.media.module.model.HDRMode;
import com.media.module.model.Quality;
import com.media.module.model.Ratio;
import com.media.module.utils.ActivityStyle;
import com.media.module.utils.CameraUtils;
import com.media.module.utils.DimenValues;
import com.media.module.utils.MResource;
import com.media.module.utils.MediaConst;
import com.media.module.utils.UIGlobalDef;
import com.media.module.view.CameraPreview;
import com.media.module.view.HeaderView;
import com.media.module.widget.FractionTranslateLayout;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import timber.log.Timber;
import uk.co.senab.photoview.PhotoView;

/**
 * 
 * 拍照
 * 
 * @author zhyc 2016年7月20日下午5:03:45 TakePhotoFragment.java
 */
public class TakePhotoFragment extends BaseFragment
		implements OnClickListener, CameraParamsChangedListener, KeyEventsListener, FocusCallback {

	private final String TAG = "CameraFragment";
	private static Context mContext;
	private ImageView mivCancel;
	private ImageView mivFlashLight;
	private ImageView mivCameraFacing;
	private ImageView mivPhotoRotate;
	private ImageView mivTakePhoto;
	private ImageView mivOK;
	// 预览照片
	private PhotoView mivPreviewPhoto;

	public static final String QUALITY = "quality";
	public static final String RATIO = "ratio";
	public static final String FOCUS_MODE = "focus_mode";
	public static final String FLASH_MODE = "flash_mode";
	public static final String HDR_MODE = "hdr_mode";
	public static final String FRONT_CAMERA = "front_camera";
	private PhotoTakenCallback mCallback;
	private RawPhotoTakenCallback mRawCallback;
	private CameraParamsChangedListener mParamsChangedListener;
	private OrientationEventListener mOrientationListener;

	private Quality mQuality;
	private Ratio mRatio;
	private FlashMode mFlashMode;
	private FacingMode mFacingMode;
	private FocusMode mFocusMode;
	private float mfBaseDimen;
	private int mintScreenWidth;
	private int mintScreenHeight;
	private Map<Ratio, Camera.Size> mPreviewSizes;
	private Map<Ratio, Map<Quality, Camera.Size>> mPictureSizes;

	private Camera mCamera;
	private Camera.Parameters mParameters;
	private CameraPreview mCameraPreview;
	private ViewGroup mvContent;
	private HDRMode mHdrMode;
	private boolean mbSupportedHDR = false;
	private boolean mbSupportedFlash = false;

	private String mstrPhotoSavePath;
	private boolean misPreview = false;
	private boolean misPixelsSet = false;
	private int mintWidthPixels;
	private int mintHeightPixels;
	private int mintCameraId;
	private int outputOrientation;
	private Bitmap mShowBitmap;
	private int mintRoateAngle;

	private float preXvaule;
	private Handler mHandler = new Handler();

	public TakePhotoFragment(Context context, Bundle params) {
		mContext = context;
		setArguments(params);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mCamera = getCameraInstance(false);
		if (mCamera == null) {
			return;
		}
		initScreenParams();
		mParameters = mCamera.getParameters();
		mPreviewSizes = buildPreviewSizesRatioMap(mParameters.getSupportedPreviewSizes());
		mPictureSizes = buildPictureSizesRatioMap(mParameters.getSupportedPictureSizes());
		List<String> sceneModes = mParameters.getSupportedSceneModes();
		if (sceneModes != null) {
			for (String mode : sceneModes) {
				if (mode.equals(Camera.Parameters.SCENE_MODE_HDR)) {
					mbSupportedHDR = true;
					break;
				}
			}
		}
		// it returns false positive
		getActivity().getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
		List<String> flashModes = mParameters.getSupportedFlashModes();
		if (flashModes == null || flashModes.size() <= 1) { // Device has no
															// flash
			mbSupportedFlash = false;
		} else {
			mbSupportedFlash = true;
		}
		if (MediaConst.DEBUG) {
			Timber.d("PictureSizesRatioMap:");
			for (Ratio r : mPictureSizes.keySet()) {
				Timber.d(r.toString() + ":");
				for (Quality q : mPictureSizes.get(r).keySet()) {
					Camera.Size size = mPictureSizes.get(r).get(q);
					if (size != null) {
						Timber.d(q.toString() + ": " + size.width + "x" + size.height);
					}
				}
			}
		}
		expandParams(getArguments());
		initParams();
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		return getContentCameraView(mContext);
	}

	/**
	 * 构造用户界面
	 * 
	 * @param context
	 * @return
	 */
	private View getContentCameraView(Context context) {
		DisplayMetrics displayMetrics = new DisplayMetrics();
		activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
		mvContent = new FractionTranslateLayout(context);
		mvContent.setBackgroundColor(Color.BLACK);

		// ImageView canvasFrame = new ImageView(mContext);
		// mCameraPreview = new CameraPreview(mContext,mCamera);
		mCameraPreview = new CameraPreview(mContext, mCamera, null, this, this);
		RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT);
		mCameraPreview.setPictureSize(mintHeightPixels, mintWidthPixels);
		mCameraPreview.setMisPixelsSet(misPixelsSet);
		mCameraPreview.setLayoutParams(params);

		// 增加画布
		mvContent.addView(mCameraPreview);
		// mvContent.addView(canvasFrame);
		// 拍照预览
		mivPreviewPhoto = new PhotoView(context);
		mvContent.addView(mivPreviewPhoto, ActivityStyle.getContentCaneraLayoutParams());
		mivPreviewPhoto.setVisibility(View.GONE);
		mivPreviewPhoto.setBackgroundColor(Color.BLACK);
		// Bottom
		LinearLayout llBottom = new LinearLayout(context);
		RelativeLayout.LayoutParams llBottomLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				(int) MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, displayMetrics) + (int) (mfBaseDimen));
		llBottomLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
		llBottomLayoutParams.setMargins(0, 0, 0,
				((int) MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, displayMetrics)));
		llBottom.setOrientation(LinearLayout.HORIZONTAL);
		llBottom.setGravity(Gravity.CENTER_VERTICAL);

		// Bottom Middle Tab
		RelativeLayout lrlBottomMiddle = new RelativeLayout(context);

		mivTakePhoto = new ImageView(context);
		mivTakePhoto.setId(UIGlobalDef.VIEW_ID.CAMERA_TAKE_PHOTO);
		String[] strStart = { "btn_shutter_photo_normal.png", "btn_shutter_photo_press.png" };
		mivTakePhoto.setImageDrawable(MResource.getSelectorDrawable(mContext, strStart));
		mivTakePhoto.setBackground(MResource.getDrawableFromAssets(mContext, "btn_shutter_circle_animation.png"));
		mivTakePhoto.setVisibility(View.VISIBLE);
		mivTakePhoto.setLayoutParams(ActivityStyle.getImageButtonLayoutParams(mfBaseDimen));
		lrlBottomMiddle.addView(mivTakePhoto);
		llBottom.addView(lrlBottomMiddle, llBottomLayoutParams);
		mivTakePhoto.setOnClickListener(this);

		mvContent.addView(llBottom, llBottomLayoutParams);
		// Top
		HeaderView llTop = new HeaderView(context);
		RelativeLayout.LayoutParams llTopLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				(int) (mfBaseDimen));
		llTopLayoutParams.setMargins(0,
				((int) MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, displayMetrics)), 0, 0);
		llTop.setOrientation(LinearLayout.HORIZONTAL);
		llTop.setLayoutParams(llTopLayoutParams);

		mvContent.addView(llTop);

		mivCancel = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CANCEL);
		mivPhotoRotate = (ImageView) mvContent.findViewById((UIGlobalDef.VIEW_ID.CAMERA_PHOTO_PREVIEW_ROATE));
		mivCameraFacing = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CAMERA_FACING);
		mivFlashLight = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.CAMERA_FLASH);
		mivOK = (ImageView) mvContent.findViewById(UIGlobalDef.VIEW_ID.OK);
		mivCancel.setOnClickListener(this);
		mivPhotoRotate.setOnClickListener(this);
		mivCameraFacing.setOnClickListener(this);
		mivFlashLight.setOnClickListener(this);
		mivOK.setOnClickListener(this);

		mvContent.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				if(!misPixelsSet)return true;
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					preXvaule = event.getX();
					break;
				case MotionEvent.ACTION_MOVE:
					float motionValue = event.getX() - preXvaule;
					if (motionValue > 0 || Math.abs(motionValue) < DimenValues.dipToPx(mContext, 40)) {
						return true;
					}
					preXvaule = event.getX();
					SettingFragment fragment = new SettingFragment(mContext);
					((Activity) mContext).getFragmentManager().beginTransaction()
							.setCustomAnimations(R.animator.fragment_slide_right_in, R.animator.fragment_slide_left_out)
							.replace(UIGlobalDef.VIEW_ID.FRAME_LAYOUT, fragment).addToBackStack(null).commit();
					break;
				default:
					break;
				}
				return true;
			}
		});
		mCameraPreview.setFocusMode(mFocusMode);
		return mvContent;
	}

	/**
	 * A safe way to get an instance of the Camera object.
	 */
	private Camera getCameraInstance(boolean useFrontCamera) {
		Camera c = null;
		try {
			c = Camera.open(getCameraId(useFrontCamera));
		} catch (Exception e) {
			Timber.e(e,
					"Camera is not available (in use or does not exist).\nPlease close applications, that may use camera.");
		}
		return c;
	}

	@SuppressWarnings("deprecation")
	private int getCameraId(boolean useFrontCamera) {
		int count = Camera.getNumberOfCameras();
		int result = -1;

		if (count > 0) {
			result = 0;

			Camera.CameraInfo info = new Camera.CameraInfo();
			for (int i = 0; i < count; i++) {
				Camera.getCameraInfo(i, info);

				if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK && !useFrontCamera) {
					result = i;
					break;
				} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && useFrontCamera) {
					result = i;
					break;
				}
			}
		}
		mintCameraId = result;
		return result;
	}

	@Override
	public void onResume() {
		super.onResume();
		if (mCamera != null) {
			try {
				mCamera.reconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (mOrientationListener == null) {
			initOrientationListener();
		}
		mOrientationListener.enable();
	}

	/**
	 * 屏幕参数
	 */
	private void initScreenParams() {
		DisplayMetrics displayMetrics = new DisplayMetrics();
		activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
		mintScreenWidth = displayMetrics.widthPixels;
		mintScreenHeight = displayMetrics.heightPixels;
		mfBaseDimen = MResource.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DimenValues.BASE_VALUE, displayMetrics);
	}

	public void setCallback(PhotoTakenCallback callback) {
		this.mCallback = callback;
	}

	public void setRawCallback(RawPhotoTakenCallback rawCallback) {
		this.mRawCallback = rawCallback;
	}

	public void setParamsChangedListener(CameraParamsChangedListener paramsChangedListener) {
		this.mParamsChangedListener = paramsChangedListener;
	}

	private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {

		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			if (data != null) {
				if (mFacingMode == FacingMode.FRONT && (outputOrientation == 90 || outputOrientation == 270)) {
					mShowBitmap = BitmapHelper.convertMirrorBmp(BitmapHelper.convertBytes2Bimap(data), -1, -1);
				} else {
					mShowBitmap = BitmapHelper.convertBytes2Bimap(data);
				}
				mivFlashLight.setVisibility(View.GONE);
				mivCameraFacing.setVisibility(View.GONE);
				mivOK.setVisibility(View.VISIBLE);
				mivTakePhoto.setVisibility(View.GONE);
				mCamera.stopPreview();
				if (misPreview) {
					mivPreviewPhoto.setImageBitmap(mShowBitmap);
					mivPreviewPhoto.setVisibility(View.VISIBLE);
					mivPhotoRotate.setVisibility(View.VISIBLE);
					mCamera.startPreview();
				}
			}

		}
	};

	@SuppressWarnings("deprecation")
	private Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {

		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
			if (mRawCallback != null && data != null) {
				mRawCallback.rawPhotoTaken(data.clone());
			}
		}

	};

	@Override
	public void onPause() {
		super.onPause();
		System.out.println("pause");
		if (mOrientationListener != null) {
			mOrientationListener.disable();
			mOrientationListener = null;
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (mCamera != null) {
			mCamera.release();
			mCamera = null;
		}
		if (mOrientationListener != null) {
			mOrientationListener.disable();
			mOrientationListener = null;
		}
	}

	public void takepicture() {
		// shutter:快门被按下 raw:相机所捕获的原始数据 jpeg:相机处理的数据
		Parameters parameters = mCamera.getParameters();
		// 设置闪光灯为自动状态
		parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
		// 设置JPG照片的质量
		parameters.setJpegQuality(100);
		if (mCamera.getParameters().isSmoothZoomSupported()) {
			parameters.setFocusMode("auto");
		}
		if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
			mCamera.setDisplayOrientation(90); // 在2.2以上可以使用
			parameters.setRotation(90);// 镜头角度转90度（默认摄像头是横拍）
			parameters.set("orientation", "portrait");
		} else {
			mCamera.setDisplayOrientation(0); // 在2.2以上可以使用
			parameters.setRotation(0);
			parameters.set("orientation", "landscape"); //
		}
		mCamera.setParameters(parameters);
		mCamera.takePicture(null, rawPictureCallback, pictureCallback);
	}

	private void expandParams(Bundle params) {
		if (params == null) {
			params = new Bundle();
		}
		if (params.containsKey(MediaConst.SHOW_CAMERA_PREVIEW)) {
			misPreview = params.getBoolean(MediaConst.SHOW_CAMERA_PREVIEW, false);
		}
		if (params.containsKey(MediaConst.SHOW_PIXELS_SET)) {
			misPixelsSet = params.getBoolean(MediaConst.SHOW_PIXELS_SET, false);
		}

		if (params.containsKey(MediaConst.OUTPUT_PHOTO_HEIGHT_PX)
				&& params.containsKey(MediaConst.OUTPUT_PHOTO_WIDTH_PX)) {
			mintHeightPixels = params.getInt(MediaConst.OUTPUT_PHOTO_HEIGHT_PX, 0);
			mintWidthPixels = params.getInt(MediaConst.OUTPUT_PHOTO_WIDTH_PX, 0);
		}

		if (params.containsKey(MediaConst.OUTPUT_PHOTO_PATH)) {
			mstrPhotoSavePath = params.getString(MediaConst.OUTPUT_PHOTO_PATH);
			Fileutils.createDir(mstrPhotoSavePath);
		}
		int id = 0;
		if (params.containsKey(RATIO)) {
			id = params.getInt(RATIO, 1);
		}
		mRatio = Ratio.getRatioById(id);
		id = 0;
		if (params.containsKey(QUALITY)) {
			id = params.getInt(QUALITY, 0);
		}
		mQuality = Quality.getQualityById(id);
		id = 0;
		if (params.containsKey(FOCUS_MODE)) {
			id = params.getInt(FOCUS_MODE);
		}
		mFocusMode = FocusMode.getFocusModeById(id);
		id = 0;
		if (params.containsKey(FLASH_MODE)) {
			id = params.getInt(FLASH_MODE);
		}
		mFlashMode = FlashMode.getFlashModeById(id);
		id = 0;
		if (params.containsKey(HDR_MODE)) {
			id = params.getInt(HDR_MODE);
		}
		mHdrMode = HDRMode.getHDRModeById(id);
	}

	private void initParams() {
		mFocusMode = FocusMode.TOUCH;
		mFlashMode = FlashMode.OFF;
		mFacingMode = FacingMode.BACK;
//		setFlashMode(mParameters, mFlashMode);
//		setPreviewSize(mParameters, mRatio);
//		setHDRMode(mParameters, mHdrMode);
//		setPictureSize(mParameters, mQuality, mRatio);
		mCamera.setParameters(mParameters);
	}

	@Override
	public void onQualityChanged(int id) {
		mQuality = Quality.getQualityById(id);
		setPictureSize(mParameters, mQuality, mRatio);
		mCamera.setParameters(mParameters);
		if (mParamsChangedListener != null) {
			mParamsChangedListener.onQualityChanged(id);
		}
	}

	@Override
	public void onRatioChanged(int id) {
		mRatio = Ratio.getRatioById(id);
		setPreviewSize(mParameters, mRatio);
		setPictureSize(mParameters, mQuality, mRatio);
		mCamera.setParameters(mParameters);
		setPreviewContainerSize(mintScreenWidth, mintScreenHeight, mRatio);
		if (mParamsChangedListener != null) {
			mParamsChangedListener.onRatioChanged(id);
		}
	}

	@Override
	public void onHDRChanged(int id) {
		mHdrMode = HDRMode.getHDRModeById(id);
		setHDRMode(mParameters, mHdrMode);
		mCamera.setParameters(mParameters);
		if (mParamsChangedListener != null) {
			mParamsChangedListener.onHDRChanged(id);
		}
	}

	@Override
	public void onFlashModeChanged(int id) {
		if (mParamsChangedListener != null) {
			mParamsChangedListener.onFlashModeChanged(id);
		}
	}

	private void switchFlashMode() {
		switch (mFlashMode) {
		case TOUCH:
			mFlashMode = FlashMode.OFF;
			break;
		case OFF:
			mFlashMode = FlashMode.TOUCH;
			break;
		default:
			break;
		}
		mParameters = mCameraPreview.getParameters();
		setFlashMode(mParameters, mFlashMode);
		mCamera.setParameters(mParameters);
		
	}

	private void switchFacingMode() {
		switch (mFacingMode) {
		case FRONT:
			mFacingMode = FacingMode.BACK;
			if (mbSupportedFlash) {
				mivFlashLight.setVisibility(View.VISIBLE);
			}
			break;
		case BACK:
			mFacingMode = FacingMode.FRONT;
			mivFlashLight.setVisibility(View.GONE);
			break;
		default:
			break;
		}
		mCamera = mCameraPreview.switchFacingMode(mFacingMode);
	}

	private void setHDRMode(Camera.Parameters parameters, HDRMode hdrMode) {
		if (mbSupportedHDR && hdrMode == HDRMode.NONE) {
			hdrMode = HDRMode.OFF;
		}
		switch (hdrMode) {
		case ON:
			parameters.setSceneMode(Camera.Parameters.SCENE_MODE_HDR);
			break;
		case OFF:
			parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
			break;
		default:
			break;
		}
	}

	private void setFlashMode(Camera.Parameters parameters, FlashMode flashMode) {
		switch (flashMode) {
		case TOUCH:
			parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
			break;
		case OFF:
			parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
			break;
		default:
			break;
		}
		setFlashModeImage(flashMode);

	}

	private void setFlashModeImage(FlashMode flashMode) {
		if (mivFlashLight == null)
			return;
		switch (flashMode) {
		case TOUCH:
			String[] strFlashOnLight = { "ic_btn_flash_always_on.png", "ic_btn_flash_always_on_pressed.png" };
			mivFlashLight.setImageDrawable(MResource.getSelectorDrawable(mContext, strFlashOnLight));
			break;
		case OFF:
			String[] strFlashOffLight = { "ic_btn_flash_always_on.png", "ic_btn_flash_always_on_pressed.png" };
			mivFlashLight.setImageDrawable(MResource.getSelectorDrawable(mContext, strFlashOffLight));
			break;
		default:
			break;
		}
	}

	private void setPictureSize(Camera.Parameters parameters, Quality quality, Ratio ratio) {
		Camera.Size size = mPictureSizes.get(ratio).get(quality);
		if (size != null) {
			parameters.setPictureSize(size.width, size.height);
		}
	}

	private void setPreviewSize(Camera.Parameters parameters, Ratio ratio) {
		Camera.Size size = mPreviewSizes.get(ratio);
		parameters.setPreviewSize(size.width, size.height);
	}

	/**
	 * @param width
	 *            Screen width
	 * @param height
	 *            Screen height
	 * @param ratio
	 *            Required ratio
	 */
	private void setPreviewContainerSize(int width, int height, Ratio ratio) {
		height = (width / ratio.h) * ratio.w;
		mvContent.setLayoutParams(new RelativeLayout.LayoutParams(width, height));
	}

	@SuppressWarnings("deprecation")
	private Map<Ratio, Map<Quality, Camera.Size>> buildPictureSizesRatioMap(List<Camera.Size> sizes) {
		Map<Ratio, Map<Quality, Camera.Size>> map = new HashMap<Ratio, Map<Quality, Size>>();

		Map<Ratio, List<Camera.Size>> ratioListMap = new HashMap<Ratio, List<Size>>();
		for (Camera.Size size : sizes) {
			Ratio ratio = Ratio.pickRatio(size.width, size.height);
			if (ratio != null) {
				List<Camera.Size> sizeList = ratioListMap.get(ratio);
				if (sizeList == null) {
					sizeList = new ArrayList<Size>();
					ratioListMap.put(ratio, sizeList);
				}
				sizeList.add(size);
			}
		}
		for (Ratio r : ratioListMap.keySet()) {
			List<Camera.Size> list = ratioListMap.get(r);
			ratioListMap.put(r, sortSizes(list));
			Map<Quality, Camera.Size> sizeMap = new HashMap<Quality, Size>();
			int i = 0;
			for (Quality q : Quality.values()) {
				Camera.Size size = null;
				if (i < list.size()) {
					size = list.get(i++);
				}
				sizeMap.put(q, size);
			}
			map.put(r, sizeMap);
		}

		return map;
	}

	private List<Camera.Size> sortSizes(List<Camera.Size> sizes) {
		int count = sizes.size();

		while (count > 2) {
			for (int i = 0; i < count - 1; i++) {
				Camera.Size current = sizes.get(i);
				Camera.Size next = sizes.get(i + 1);

				if (current.width < next.width || current.height < next.height) {
					sizes.set(i, next);
					sizes.set(i + 1, current);
				}
			}
			count--;
		}

		return sizes;
	}

	private Map<Ratio, Camera.Size> buildPreviewSizesRatioMap(List<Camera.Size> sizes) {
		Map<Ratio, Camera.Size> map = new HashMap<Ratio, Size>();

		for (Camera.Size size : sizes) {
			Ratio ratio = Ratio.pickRatio(size.width, size.height);
			if (ratio != null) {
				Camera.Size oldSize = map.get(ratio);
				if (oldSize == null || (oldSize.width < size.width || oldSize.height < size.height)) {
					map.put(ratio, size);
				}
			}
		}
		return map;
	}

	private void initOrientationListener() {
		mOrientationListener = new OrientationEventListener(activity) {

			@Override
			public void onOrientationChanged(int orientation) {
				if (mCamera != null && orientation != ORIENTATION_UNKNOWN) {
					int newOutputOrientation = getCameraPictureRotation(orientation);

					if (newOutputOrientation != outputOrientation) {
						outputOrientation = newOutputOrientation;
						try {
							Camera.Parameters params = mCamera.getParameters();
							params.setRotation(outputOrientation);
							mCamera.setParameters(params);
						} catch (Exception e) {
							Timber.e(e, "Exception updating camera parameters in orientation change");
						}
					}
				}
			}
		};
	}

	private int getCameraPictureRotation(int orientation) {
		Camera.CameraInfo info = new Camera.CameraInfo();
		try {
			Camera.getCameraInfo(mintCameraId, info);
		} catch (Exception e) {
			// TODO: handle exception
		}
		int rotation;
		orientation = (orientation + 45) / 90 * 90;
		if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
			rotation = (info.orientation - orientation + 360) % 360;
		} else { // back-facing camera
			rotation = (info.orientation + orientation) % 360;
		}
		return (rotation);
	}

	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case UIGlobalDef.VIEW_ID.CANCEL:
			if (mivPreviewPhoto.getVisibility() == View.VISIBLE) {
				mivPreviewPhoto.setVisibility(View.GONE);
				mivOK.setVisibility(View.GONE);
				mivTakePhoto.setVisibility(View.VISIBLE);
				mivCameraFacing.setVisibility(View.VISIBLE);
				mivPhotoRotate.setVisibility(View.GONE);

				if (mFacingMode == FacingMode.BACK) {
					mivFlashLight.setVisibility(View.VISIBLE);
					setFlashMode(mParameters, FlashMode.OFF);
				}
			} else {
				getActivity().finish();
			}
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_FACING:
			switchFacingMode();
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_FLASH:
			if (mbSupportedFlash) {
				switchFlashMode();
			}
			break;
		case UIGlobalDef.VIEW_ID.PIXELS:
			Toast.makeText(mContext, "设置分辨率", Toast.LENGTH_LONG).show();
			break;
		case UIGlobalDef.VIEW_ID.OK:
			final String filePath = mstrPhotoSavePath + File.separator + "IMG_" + CameraUtils.getModifyTime() + ".jpg";
			mShowBitmap = BitmapHelper.rotateBitmap(mShowBitmap, 360 - mintRoateAngle);
			new ProgressDialogHelper(mContext).showProgressDialog("", MediaConst.MSG_LOADING, new ProgressCallBack() {

				@Override
				public void action() {
					Fileutils.createDir(mstrPhotoSavePath);
					Fileutils.writeImageToSdcard(mShowBitmap, filePath, CompressFormat.JPEG);
					mHandler.post(new Runnable() {

						@Override
						public void run() {
							Intent intent = getActivity().getIntent();
							intent.setData(Uri.fromFile(new File(filePath)));
							getActivity().setResult(Activity.RESULT_OK, intent);
							getActivity().finish();
							if (mShowBitmap != null) {
								BitmapHelper.release(mShowBitmap);
							}

						}
					});
				}
			});
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_TAKE_PHOTO:
			takepicture();
			break;
		case UIGlobalDef.VIEW_ID.CAMERA_PHOTO_PREVIEW_ROATE:
			mintRoateAngle = (mintRoateAngle + 90) % 360;
			mivPreviewPhoto.setPhotoViewRotation(mintRoateAngle);
			break;
		default:
			break;
		}
	}

	@Override
	public void onFocused(Camera camera) {
	}

	@Override
	public void zoomIn() {
		// TODO Auto-generated method stub

	}

	@Override
	public void zoomOut() {
		// TODO Auto-generated method stub

	}

	@Override
	public void takePhoto() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onFocusModeChanged(int id) {
		mFocusMode = FocusMode.getFocusModeById(id);
		mCameraPreview.setFocusMode(mFocusMode);
		if (mParamsChangedListener != null) {
			mParamsChangedListener.onFocusModeChanged(id);
		}

	}
}
